package org.chen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.chen.exception.NewsException;
import org.chen.mapper.SysConfigMapper;
import org.chen.model.dto.SysConfigDTO;
import org.chen.model.sys.SysConfig;
import org.chen.response.PageResult;
import org.chen.service.SysConfigService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class ConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements SysConfigService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @Autowired
    private SysConfigMapper sysConfigMapper;

    private static final String CONFIG_KEY_PREFIX = "sys:config:";
    private static final long CACHE_DURATION = 1; // 缓存时长(小时)

    @Override
    public PageResult<SysConfig> getConfigList(Integer page, Integer size, String key, String category) {
        Page<SysConfig> pageParams = new Page<>(page, size);

        LambdaQueryWrapper<SysConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(key), SysConfig::getConfigKey, key)
                .eq(StringUtils.isNotBlank(category), SysConfig::getCategory, category)
                .orderByDesc(SysConfig::getUpdateTime);

        Page<SysConfig> configPage = sysConfigMapper.selectPage(pageParams, wrapper);

        return new PageResult<>(configPage.getRecords(), configPage.getTotal());
    }

    public String getConfigValue(String key) {
        String cacheKey = CONFIG_KEY_PREFIX + key;
        String value = redisTemplate.opsForValue().get(cacheKey);

        if (value != null) {
            return value;
        }

        SysConfig config = sysConfigMapper.selectOne(
                new LambdaQueryWrapper<SysConfig>()
                        .eq(SysConfig::getConfigKey, key)
        );

        if (config != null) {
            value = config.getConfigValue();
            redisTemplate.opsForValue().set(cacheKey, value, CACHE_DURATION, TimeUnit.HOURS);
            return value;
        }

        throw new NewsException("配置不存在: " + key);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addConfig(SysConfigDTO configDTO) {
// 检查是否已存在
        Long count = sysConfigMapper.selectCount(
                new LambdaQueryWrapper<SysConfig>()
                        .eq(SysConfig::getConfigKey, configDTO.getConfigKey())
        );

        if (count > 0) {
            throw new NewsException("配置已存在: " + configDTO.getConfigKey());
        }

        SysConfig config = new SysConfig();
        BeanUtils.copyProperties(configDTO, config);

        sysConfigMapper.insert(config);

        // 更新缓存
        String cacheKey = CONFIG_KEY_PREFIX + config.getConfigKey();
        redisTemplate.opsForValue().set(cacheKey, config.getConfigValue(), CACHE_DURATION, TimeUnit.HOURS);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateConfig(SysConfigDTO configDTO) {
        SysConfig config = sysConfigMapper.selectOne(
                new LambdaQueryWrapper<SysConfig>()
                        .eq(SysConfig::getConfigKey, configDTO.getConfigKey())
        );

        if (config == null) {
            throw new NewsException("配置不存在: " + configDTO.getConfigKey());
        }

        BeanUtils.copyProperties(configDTO, config);
        config.setUpdateTime(LocalDateTime.now());

        sysConfigMapper.updateById(config);

        // 更新缓存
        String cacheKey = CONFIG_KEY_PREFIX + config.getConfigKey();
        redisTemplate.opsForValue().set(cacheKey, config.getConfigValue(), CACHE_DURATION, TimeUnit.HOURS);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteConfig(String key) {
        // 检查是否是系统必需配置
        if (isSystemRequiredConfig(key)) {
            throw new NewsException("系统必需配置，不能删除: " + key);
        }

        sysConfigMapper.delete(
                new LambdaQueryWrapper<SysConfig>()
                        .eq(SysConfig::getConfigKey, key)
        );

        // 删除缓存
        String cacheKey = CONFIG_KEY_PREFIX + key;
        redisTemplate.delete(cacheKey);
    }

    private boolean isSystemRequiredConfig(String key) {
        // 在这里定义系统必需的配置项
        Set<String> requiredConfigs = Set.of(
                "article.admin.upload-path",
                "article.admin.access-path"
                // 添加其他必须
        );
        return requiredConfigs.contains(key);
    }
}